package com.audaque.springboot.foshanupload.jwtcore.component;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.AlgorithmUtil;
import cn.hutool.jwt.signers.JWTSigner;
import com.audaque.springboot.foshanupload.jwtcore.component.iface.JwtProviderIface;


import com.audaque.springboot.foshanupload.jwtcore.properties.JwtProperties;
import com.google.common.base.Charsets;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.security.KeyPair;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zgb
 * @desc ...
 * @date 2022-06-29 20:50:13
 */
@ConditionalOnExpression("${switch.hutoolJwtHs256Provider}")
@Component
@Slf4j
public class HutoolJwtHs256Provider implements JwtProviderIface {
    @Autowired
    private JwtProperties jwtProperties;

    public String generateKeyStr() {
        String algorithmId = jwtProperties.getAlgorithmId();
        //对称加密
        String algorithm = AlgorithmUtil.getAlgorithm(algorithmId);
        SecretKey secretKey = KeyUtil.generateKey(algorithm);
        String format = secretKey.getFormat();
        byte[] encoded = secretKey.getEncoded();
        String s1 = Base64.getEncoder().encodeToString(secretKey.getEncoded());
        String algorithm1 = secretKey.getAlgorithm();
        String s = secretKey.toString();
        return s1;
    }

    public SecretKey generateKey() {
        String algorithmId = jwtProperties.getAlgorithmId();
        //对称加密
        String algorithm = AlgorithmUtil.getAlgorithm(algorithmId);
        SecretKey secretKey = KeyUtil.generateKey(algorithm);
        return secretKey;
    }



    public KeyPair generateKeyPair() {
        String algorithmId = jwtProperties.getAlgorithmId();
        //对称加密
        String algorithm = AlgorithmUtil.getAlgorithm(algorithmId);
        KeyPair keyPair = KeyUtil.generateKeyPair(algorithm);
        return keyPair;
    }

    public String getAccessToken(Map<String, Object> map) {
        //加密生成token
        String algorithmId = jwtProperties.getAlgorithmId();
        String skey = jwtProperties.getSkey();
        String privateKey = jwtProperties.getPrivateKey();
        String publicKey = jwtProperties.getPublicKey();
        Map<String, Object> headers = new HashMap<>();
        Map<String, Object> playloads = new HashMap<>();
        playloads = map;
        JWT jwt = JWT.create();
        jwt.setCharset(Charsets.UTF_8);
        jwt.addHeaders(headers);
        jwt.addPayloads(playloads);
        Long expires = jwtProperties.getExpires();
        long current = DateUtil.current();
        expires += current;
        DateTime expiresAt = DateUtil.date(expires);
        jwt.setExpiresAt(expiresAt);
        String issuer = jwtProperties.getIssuer();
        jwt.setIssuer(issuer);
        DateTime currentDate = DateUtil.date(current);
        jwt.setIssuedAt(currentDate);
        //setKey对应用到默认算法：hs256
        jwt.setKey(skey.getBytes());
        jwt.setNotBefore(currentDate);
        jwt.setSubject("access token");
        String accessToken = jwt.sign();
        return accessToken;
    }


    public String getBody(String accessToken) {
        JWT jwt = this.getJwt(accessToken);
        JWTPayload payload = jwt.getPayload();
        JSONObject claimsJson = payload.getClaimsJson();
        String s = JSONUtil.toJsonStr(claimsJson);
        return s;
    }


    private JWT getJwt(String accessToken) {
        boolean b = this.verifyJwtStr(accessToken);
        if (!b) {
            return null;
        }
        JWT jwt = JWTUtil.parseToken(accessToken);

        b = this.verifyJwt(jwt);
        if (!b) {
            return null;
        }
        return jwt;
    }



    private boolean verifyJwtStr(String accessToken) {
        String skey = jwtProperties.getSkey();
        boolean verify = JWTUtil.verify(accessToken, skey.getBytes());
        return verify;

    }




    private boolean verifyJwt(JWT jwt ) {
        String algorithm = jwt.getAlgorithm();
        JSONObject headers = jwt.getHeaders();
        JSONObject payloads = jwt.getPayloads();
        JWTSigner signer = jwt.getSigner();
        String skey = jwtProperties.getSkey();
        boolean verifyKey = jwt.setKey(skey.getBytes()).verify();
        boolean verifyTime = jwt.validate(0);
        if(verifyKey&&verifyTime){
            return true;
        }else{
            return false;
        }

    }






}


